package com.dcivision.workflow.core;

import java.sql.Connection;
import java.util.Iterator;
import java.util.List;

import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.ApplicationExceptionList;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.Utility;
import com.dcivision.staff.bean.StaffRecord;
import com.dcivision.staff.dao.StaffRecordDAObject;
import com.dcivision.user.bean.UserRecord;
import com.dcivision.user.dao.UserRecordDAObject;
import com.dcivision.workflow.bean.MtmWorkflowProgressUserRecord;
import com.dcivision.workflow.bean.MtmWorkflowStepUserActor;
import com.dcivision.workflow.bean.WorkflowProgress;
import com.dcivision.workflow.bean.WorkflowStep;
import com.dcivision.workflow.dao.MtmWorkflowProgressUserRecordDAObject;
import com.dcivision.workflow.dao.MtmWorkflowStepUserActorDAObject;
import com.dcivision.workflow.dao.WorkflowProgressDAObject;
import com.dcivision.workflow.dao.WorkflowStepDAObject;
/**
 * 
 * @author TC.tang
 * @createDate 2007-2-6
 */
public class WorkflowProgressActionTakerCheckerManager {

  private SessionContainer sessionCon = null;
  private Connection       dbConn     = null;
  
  public WorkflowProgressActionTakerCheckerManager(SessionContainer sessionCon,Connection dbConn){
    this.sessionCon = sessionCon;
    this.dbConn     = dbConn;
  }
  /**
   * check current User can submit this workflow
   * @param workflowRecordID
   * @return
   * @throws ApplicationException
   */
  //with default User
  public boolean checkIfThisUserCanSubmitThisWorkflow(Integer workflowRecordID) throws ApplicationException{
    return checkIfThisUserCanSubmitThisWorkflow(workflowRecordID,this.sessionCon.getUserRecordID());
  }
  
  public boolean checkIfThisUserCanSubmitThisWorkflow(Integer workflowRecordID,Integer userID) throws ApplicationException{
    WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(sessionCon,dbConn);
    WorkflowStep submitStep = (WorkflowStep)stepDAO.getSubmitStepByWorkflowRecordID(workflowRecordID);
    
    //0.check if any step only have one actionTaker : submitSuperVisor
    checkSubmitersSupervisor(workflowRecordID,new String[]{"W"});
    //1.check if have any actionTaker to handle the next progress
    checkHaveAnyActionTakerToHandleNextStepWithPermission(submitStep.getID(),new String[]{"W"},null,userID);
    //2.check none-actionTaker steps
    checkStepWithNoActionTaker(workflowRecordID,new String[]{"W"});
    
    return true;//pass the check
  }
  
  /**
   * check currentUser can operate this progress(approve/complete/yes...)
   * @param progress
   * @return
   * @throws ApplicationException
   */
  //width default User
  public boolean checkIfThisUserCanOperationThisTask(WorkflowProgress progress) throws ApplicationException{
    return checkIfThisUserCanOperationThisTask(progress,this.sessionCon.getUserRecordID());
  }
  
  public boolean checkIfThisUserCanOperationThisTask(WorkflowProgress progress,Integer userID) throws ApplicationException{
    //0.check have any actionTaker to handle next progress
    checkHaveAnyActionTakerToHandleNextStepWithPermission(progress.getWorkflowStepID(),new String[]{"W"},progress.getTrackID(),userID);
    //1.check have any step which only have one actionTaker is this.progress's actionTaker's supervisor
    checkSomeStepWhichActionTakerIsThisStepActionTakersSupervisorOnly(progress.getWorkflowStepID(),new String[]{"W"});
    return true;//pass the check
  }
  /**
   * check if this workflow have some step which only have one actionTaker which is Submiter's supervisor
   * @param workflowRecordID
   * @param permissions
   * @return
   * @throws ApplicationException
   */
  private boolean checkSubmitersSupervisor(Integer workflowRecordID,String[] permissions) throws ApplicationException{
    WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(sessionCon, dbConn);
    MtmWorkflowStepUserActorDAObject stepUserActorDAO = new MtmWorkflowStepUserActorDAObject(sessionCon, dbConn);
    
   
    //get the Step which  have  actionUser:submitterSupervisor
    List actionUserIsSubmitterSuperVisorStepList = stepDAO.getSubmitterSuperVisorStepListByWorkflowRecordIDWithPermissions(workflowRecordID,permissions);
    //check if the StaffRecord have SuperVisor
    boolean haveSuperVisor = hasSupervisor(sessionCon.getUserRecord());
    
    for(Iterator it=actionUserIsSubmitterSuperVisorStepList.iterator();it.hasNext();){
      
      WorkflowStep step = (WorkflowStep)it.next();
      //List stepUserList=stepDAO.getUserListByStepID(step.getID());
      List actionTakerList = stepUserActorDAO.getListByWorkflowStepIDAndActorTypeAndPermissions(step.getID(), MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO,permissions);
      Integer stepUserListCount = stepUserActorDAO.getListCountByWorkflowStepIDAndPermissions(step.getID(),permissions);
      if(stepUserListCount.intValue()==0){
        //have no user,did not check. No User condition should be checked when create step or release workflow
        //when at here,no User record will be reasonable
        return true;
      }
      //if Step only have one UserActor which is SuperVisior but StaffRecord have on SuperVisor
      if((actionTakerList.size()>=stepUserListCount.intValue())&&!haveSuperVisor){
        throw new ApplicationException("errors.workflow.must_have_reportto_staff",null, new String[]{step.getStepName()});
      }
    }
    return true;
  }
  
  /**
   * check if have any actionTaker to handle next Step
   * @param workflowStepID
   * @param permissions
   * @return
   * @throws ApplicationException
   */
  private boolean checkHaveAnyActionTakerToHandleNextStepWithPermission(Integer workflowStepID,String[] permissions,Integer trackID,Integer submitterID) throws ApplicationException{
    WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(sessionCon, dbConn);
    List childStepList = stepDAO.getDistinctListByParentStepID(workflowStepID);
    for(Iterator it=childStepList.iterator();it.hasNext();){
      WorkflowStep childStep = (WorkflowStep)it.next();
      
      if(WorkflowStep.END_STEP_SEQ_NO.equals(childStep.getStepSeq())){
        continue;
        //if end Step ,do not check
      }
      if(WorkflowStep.ACTION_TYPE_SYSTEM_AUTO.equals(childStep.getActionType())){
        continue;
        //if system auto,do not check
      }
      if(WorkflowStep.ACTION_TYPE_FORM_DRIVEN.equals(childStep.getActionType())){
        continue;
        //if Form Drivern,do not check
      }
      
      checkHaveAnyActionTakerToHandleThisStepWithPermission(childStep,permissions,trackID,submitterID);//if can not pass,will throw exception
    }
    return true;//pass the check
  }
  
  /**
   * check this step have any actionTaker to Handle
   * @param workflowStepID
   * @param permissions
   * @return
   * @throws ApplicationException
   */
  private boolean checkHaveAnyActionTakerToHandleThisStepWithPermission(WorkflowStep workflowStep,String[] permissions,Integer trackID,Integer submitterID) throws ApplicationException{
    //if can not pass,will throw the exception
    ApplicationExceptionList exceptionList = new ApplicationExceptionList();
    
    MtmWorkflowStepUserActorDAObject stepUserActorDAO = new MtmWorkflowStepUserActorDAObject(sessionCon, dbConn);
    Integer stepUserListCount = stepUserActorDAO.getListCountByWorkflowStepIDAndPermissions(workflowStep.getID(),permissions);//all user count
    //1. supervisor of preStep
    Integer supervisorOfPreviousStepCount = stepUserActorDAO.getListCountByWorkflowStepIDAndActorTypeAndPermissions(workflowStep.getID(), MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO_OF_PREVIOUS_TASK_ACTION_TAKER, permissions);//get special User Count
    //2. supervisor of some step
    Integer supervisorOfSomeStepCount = stepUserActorDAO.getListCountByWorkflowStepIDAndActorTypeAndPermissions(workflowStep.getID(), MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO_OF_ACTION_TAKER, permissions);
    //3. supervisor of submitter
    Integer supervisorOfSubmitter = stepUserActorDAO.getListCountByWorkflowStepIDAndActorTypeAndPermissions(workflowStep.getID(), MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO, permissions);
    
    if(stepUserListCount.intValue()==0){
    //have on User,did not check
      return true;
    }
    
    if(stepUserListCount.intValue()>(supervisorOfPreviousStepCount.intValue()+supervisorOfSomeStepCount.intValue()+supervisorOfSubmitter.intValue())){
      //have Other normal User
      return true;
    }
    //check previous Step actionTaker's superVisor
    if(supervisorOfPreviousStepCount.intValue()>0){
      if(checkPreviousStepActionTakerSuperVisorWithPermission(workflowStep.getID(),permissions)){
        return true;
      }else{
      //add exception
        exceptionList.addException(new ApplicationException("errors.workflow.must_have_previousTask_actionTaker_reportto",null,new String[]{workflowStep.getStepName()}));
      }
    }
    //check some Step actionTaker's superVisor 
    if(!Utility.isEmpty(trackID)&&supervisorOfSomeStepCount.intValue()>0){
      if(checkSomeStepActionTakerSuperVisorWithPermission(workflowStep.getID(),permissions,trackID)){
        return true;
      }else{
        //add exception
        exceptionList.addException(new ApplicationException("errors.workflow.must_have_someTask_actionTaker_reportto",null,new String[]{workflowStep.getStepName(),"this step"}));
      } 
    }
    
    if(supervisorOfSubmitter.intValue()>0){
      if(checkSubmitterSupervisorWithPermission(workflowStep.getID(),permissions,trackID,submitterID)){
        return true;
      }else{
      //add exception
        exceptionList.addException(new ApplicationException("errors.workflow.must_have_reportto_staff",null,new String[]{workflowStep.getStepName()}));
      }
    }
    //throw exception here
    exceptionList.throwException();
    return true;
  }
 
  /**
   * check previous step actionTaker's supervisor
   * @param workflowStepID
   * @param permissions
   * @return
   * @throws ApplicationException
   */
  private boolean checkPreviousStepActionTakerSuperVisorWithPermission(Integer workflowStepID,String[] permissions) throws ApplicationException{
    MtmWorkflowStepUserActorDAObject stepUserActorDAO = new MtmWorkflowStepUserActorDAObject(this.sessionCon,this.dbConn);
    return checkPreviousStepActionTakerSuperVisorWithPermission(stepUserActorDAO,workflowStepID,permissions);
  }
  private boolean checkPreviousStepActionTakerSuperVisorWithPermission(MtmWorkflowStepUserActorDAObject stepUserActorDAO,Integer workflowStepID,String[] permissions) throws ApplicationException{
    
    boolean haveSuperVisor = hasSupervisor(sessionCon.getUserRecord());
     
    List previousActionTakerList = stepUserActorDAO.getListByWorkflowStepIDAndActorTypeAndPermissions(workflowStepID, MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO_OF_PREVIOUS_TASK_ACTION_TAKER,permissions);
    if(!Utility.isEmpty(previousActionTakerList)){
      if(!haveSuperVisor){
      //need pervious step actionTaker's supervisor,but this user have't
        return false;
      }else{
        return true;//need previous step actionTaker's supervisor and have this user
      }
    }
    return true;//didn't have previous
  }
  
  /**
   * check some step actionTaker supervisor
   * @param workflowStepID
   * @param permissions
   * @return
   * @throws ApplicationException 
   */
  private boolean checkSomeStepActionTakerSuperVisorWithPermission(Integer workflowStepID,String[] permissions,Integer trackID) throws ApplicationException{
    MtmWorkflowStepUserActorDAObject stepUserActorDAO = new MtmWorkflowStepUserActorDAObject(this.sessionCon,this.dbConn);
    return checkSomeStepActionTakerSuperVisorWithPermission(stepUserActorDAO,workflowStepID,permissions,trackID);
  }
  private boolean checkSomeStepActionTakerSuperVisorWithPermission(MtmWorkflowStepUserActorDAObject stepUserActorDAO,Integer workflowStepID,String[] permissions,Integer trackID) throws ApplicationException{
    //0.select all someStepActionTaker's supervisor
    //1.check x of someStepactionTaker's supervisor is exists
    List someStepActionTakerSupervisorList = stepUserActorDAO.getListByWorkflowStepIDAndActorTypeAndPermissions(workflowStepID, MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO_OF_ACTION_TAKER,permissions);
    if(Utility.isEmpty(someStepActionTakerSupervisorList)){
      return true;//have't 'T' actor Type
    }
    
    for(Iterator it=someStepActionTakerSupervisorList.iterator();it.hasNext();){
      // get the somestep'actionTaker
      MtmWorkflowStepUserActor stepUseractor = (MtmWorkflowStepUserActor)it.next();
      boolean haveSuperVisor = hasSupervisor(stepUseractor,trackID);
      if(haveSuperVisor){
        return true;//have the actionTaker
      }
    }
    return false;
  }
  
  /**
   * check the submitter's supervisor with permission
   * @param step
   * @param permissions
   * @return
   * @throws ApplicationException 
   */
  private boolean checkSubmitterSupervisorWithPermission(Integer stepID,String[] permissions,Integer trackID,Integer submitterID) throws ApplicationException{
    
    if(Utility.isEmpty(submitterID)){
    MtmWorkflowProgressUserRecordDAObject progressUserDAO = new MtmWorkflowProgressUserRecordDAObject(this.sessionCon,this.dbConn);
    WorkflowProgressDAObject progressDAO = new WorkflowProgressDAObject(this.sessionCon,this.dbConn);
    WorkflowProgress firstProgress = (WorkflowProgress)progressDAO.getFirstProgressByTrackID(trackID);
    List submitterList = progressUserDAO.getListByWorkflowProgressID(firstProgress.getID(), WorkflowProgress.STATUS_SUBMIT);
    MtmWorkflowProgressUserRecord mtmProgressSubmitUser = (MtmWorkflowProgressUserRecord)submitterList.get(0);
    submitterID = mtmProgressSubmitUser.getUserRecordID();
    //get the submitterID finished
    }
    
    boolean haveSupervisor = this.hasSupervisor(submitterID);
    
    MtmWorkflowStepUserActorDAObject stepActorDAO = new MtmWorkflowStepUserActorDAObject(this.sessionCon,this.dbConn);
    //check if this step need submittersupervisor
    Integer sbumitterSupervisorCount = stepActorDAO.getListCountByWorkflowStepIDAndActorIDAndActorTypeAndPermissions(stepID, new Integer(0), MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO, permissions);
    if(sbumitterSupervisorCount.intValue()>0){
      if(haveSupervisor){
        return true;//have submittersupervisor
      }
    }
    return false;
  }
  /**
   * check if 
   * @param stepID
   * @param permissions
   * @param param
   * @return
   * @throws ApplicationException 
   * @throws ApplicationException
   */
  private boolean checkSomeStepWhichActionTakerIsThisStepActionTakersSupervisorOnly(Integer stepID,String[] permissions) throws ApplicationException{
    //if have some step only have one actionTaker which is this step actionTaker's supervisor
    String[] param = new String[1];
    if(haveSomeStepWhichActionTakerIsThisStepActionTakersSupervisorOnly(stepID,permissions,param)){
      //throw exception here
      throw new ApplicationException("errors.workflow.must_have_someTask_actionTaker_reportto",null,new String[]{param[0],"this step"}); 
    }
    return true;//check pass
  }
  private boolean haveSomeStepWhichActionTakerIsThisStepActionTakersSupervisorOnly(Integer stepID,String[] permissions,String[] param) throws ApplicationException{
    //check if have some Step which actionTaker is this step actionTaker's supervisor
    MtmWorkflowStepUserActorDAObject stepUserActorDAO = new MtmWorkflowStepUserActorDAObject(sessionCon, dbConn);
    WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(sessionCon, dbConn);
    
    List actionTakerList = stepUserActorDAO.getListWorkflowStepIDByActorIDAndActorTypeAndPermissions(stepID, MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO_OF_ACTION_TAKER,permissions);
    for(Iterator it=actionTakerList.iterator();it.hasNext();){
      MtmWorkflowStepUserActor stepUseractor = (MtmWorkflowStepUserActor)it.next();
      WorkflowStep step=(WorkflowStep)stepDAO.getObjectByID(stepUseractor.getWorkflowStepID());
      if(isOnlyHaveSomeStepActionTakersSupervisor(step,permissions,stepUserActorDAO)){
        //have one step which actionTaker is this step's actionTaker's supervisor only
        param[0]=step.getStepName();//for return
        return true;
      }
    }
    return false;//not contains any step which actionTaker is this step actionTaker's supervisor only
  }
  
  public boolean isOnlyHaveSomeStepActionTakersSupervisors(WorkflowStep step,String[] permissions)throws ApplicationException{
    MtmWorkflowStepUserActorDAObject stepUserActorDAO = new MtmWorkflowStepUserActorDAObject(sessionCon, dbConn);
    return  isOnlyHaveSomeStepActionTakersSupervisor(step,permissions,stepUserActorDAO);
  }
  private boolean isOnlyHaveSomeStepActionTakersSupervisor(WorkflowStep step,String[] permissions,MtmWorkflowStepUserActorDAObject stepUserActorDAO)throws ApplicationException{
    Integer haveWritePermissionUserCount = stepUserActorDAO.getListCountByWorkflowStepIDAndPermissions(step.getID(), permissions);
    if(haveWritePermissionUserCount.intValue()<=1){
      return true;
    }
    return false;//have other actionTaker which have current permission
  }
  
  /**
   * check the step which have no ActionTaker and have some step which actionTaker is this step's actionTaker's supervisor only
   * @param workflowRecordID
   * @return
   * @throws ApplicationException 
   */
  private boolean checkStepWithNoActionTaker(Integer workflowRecordID,String[] permissions) throws ApplicationException{
    //0.select all step of this workflowRecord
    //1.if is auto,form driven should check
    //2.if have some step which actionTaker is this step's actionTaker or this actionTaker's supervisor only or (this step's actionTaker and this actionTaker's supervisor)
    //3.if this step's child step which actionTaker is previous only or previous supervisor only or (pre actionTaker and pre actionTaker supervisor)
    WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(this.sessionCon,this.dbConn);
    List stepList = stepDAO.getListByWorkflowRecordID(workflowRecordID);
    for(Iterator it=stepList.iterator();it.hasNext();){
      WorkflowStep step = (WorkflowStep)it.next();
      if(WorkflowStep.END_STEP_SEQ_NO.equals(step.getStepSeq())){
        continue;//end egnore
      }
      if(WorkflowStep.ACTION_TYPE_SYSTEM_AUTO.equals(step.getActionType())
          ||WorkflowStep.ACTION_TYPE_FORM_DRIVEN.equals(step.getActionType())){
        //this step haven't actionTaker
        String[] param = new String[1];
        //check some step relate to this NONE-ACTIONTAKER STEP
        if(!checkSomeStepRelateToCurrentNoneActionTakerStep(stepDAO,step,permissions,param)){
          //throw exception here
          throw new ApplicationException("errors.workflow.must_have_someTask_actionTaker_reportto",null,new String[]{param[0],step.getStepName()}); 
        }
        //check child step of this NONE_ACTIONTAKER STEP
        if(!checkChildStepOfCurrentNoneActionTakerStep(stepDAO,step,permissions,param)){
        //throw exception here
          throw new ApplicationException("errors.workflow.must_have_someTask_actionTaker_reportto",null,new String[]{param[0],step.getStepName()}); 
        }
      }
    }
    return true;//pass the check
  }
  
  private boolean checkSomeStepRelateToCurrentNoneActionTakerStep(WorkflowStepDAObject stepDAO,WorkflowStep step,String[] permissions,String[] param) throws ApplicationException{
    List stepList = stepDAO.getListByWorkflowRecordID(step.getWorkflowRecordID());
    
    MtmWorkflowStepUserActor[] userActors = null;
    boolean submitterHaveSupervisor = hasSupervisor(sessionCon.getUserRecord());
    if(submitterHaveSupervisor){
      userActors = new MtmWorkflowStepUserActor[2];
    }else{
      userActors = new MtmWorkflowStepUserActor[3];
    }
    
    int i=0;
    
    MtmWorkflowStepUserActor reportOfActionTaker = new MtmWorkflowStepUserActor();
    reportOfActionTaker.setActorID(step.getID());
    reportOfActionTaker.setActorType(MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO_OF_ACTION_TAKER);
    userActors[i++]=reportOfActionTaker;
    MtmWorkflowStepUserActor actionTaker = new MtmWorkflowStepUserActor();
    actionTaker.setActorID(step.getID());
    actionTaker.setActorType(MtmWorkflowStepUserActor.ACTOR_TYPE_ACTION_TAKER);
    userActors[i++]=actionTaker;
    if(!submitterHaveSupervisor){
      //if submitter have the supervisor,the special user should contains submitter's supervisor
      //becase this step's actionTaker contains submitter's supervisor,it can work
      MtmWorkflowStepUserActor reportOfsubmitter = new MtmWorkflowStepUserActor();
      reportOfsubmitter.setActorID(new Integer(0));
      reportOfsubmitter.setActorType(MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO);
      userActors[i++]=reportOfsubmitter;
    }
    return checkStepRelateToCurrentNoneActionTakerStep(stepList,step,userActors,permissions,param);
  }
  
  private boolean checkChildStepOfCurrentNoneActionTakerStep(WorkflowStepDAObject stepDAO,WorkflowStep step,String[] permissions,String[] param) throws ApplicationException{
    List stepList = stepDAO.getDistinctListByParentStepID(step.getID());
    
    MtmWorkflowStepUserActor[] userActors = null;
    boolean submitterHaveSupervisor = hasSupervisor(sessionCon.getUserRecord());
    if(submitterHaveSupervisor){
      userActors = new MtmWorkflowStepUserActor[4];
    }else{
      userActors = new MtmWorkflowStepUserActor[5];
    }
    int i=0;
    
    MtmWorkflowStepUserActor reportOfActionTaker = new MtmWorkflowStepUserActor();
    reportOfActionTaker.setActorID(step.getID());
    reportOfActionTaker.setActorType(MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO_OF_ACTION_TAKER);
    userActors[i++]=reportOfActionTaker;
    MtmWorkflowStepUserActor actionTaker = new MtmWorkflowStepUserActor();
    actionTaker.setActorID(step.getID());
    actionTaker.setActorType(MtmWorkflowStepUserActor.ACTOR_TYPE_ACTION_TAKER);
    userActors[i++]=actionTaker;
    if(!submitterHaveSupervisor){
      //if submitter have the supervisor,the special user should contains submitter's supervisor
      //because if childStep have submitter's supervisor user type,it can work
      MtmWorkflowStepUserActor reportOfsubmitter = new MtmWorkflowStepUserActor();
      reportOfsubmitter.setActorID(new Integer(0));
      reportOfsubmitter.setActorType(MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO);
      userActors[i++]=reportOfsubmitter;
    }
    MtmWorkflowStepUserActor reportOfPrevious = new MtmWorkflowStepUserActor();
    reportOfPrevious.setActorID(new Integer(0));
    reportOfPrevious.setActorType(MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO_OF_PREVIOUS_TASK_ACTION_TAKER);
    userActors[i++]=reportOfPrevious;
    MtmWorkflowStepUserActor previousTaker = new MtmWorkflowStepUserActor();
    previousTaker.setActorID(new Integer(0));
    previousTaker.setActorType(MtmWorkflowStepUserActor.ACTOR_TYPE_PREVIOUS_TASK_ACTION_TAKER);
    userActors[i++]=previousTaker;
    
    return checkStepRelateToCurrentNoneActionTakerStep(stepList,step,userActors,permissions,param);
  }
  
  private boolean checkStepRelateToCurrentNoneActionTakerStep(List stepList,WorkflowStep step,MtmWorkflowStepUserActor[] mtmWorkflowStepUserActors,String[] permissions,String[] param) throws ApplicationException{
    
    MtmWorkflowStepUserActorDAObject actorDAO = new MtmWorkflowStepUserActorDAObject(this.sessionCon,this.dbConn);
    for(Iterator it=stepList.iterator();it.hasNext();){
      WorkflowStep tempStep = (WorkflowStep)it.next();
      if(WorkflowStep.END_STEP_SEQ_NO.equals(tempStep.getStepSeq())){
        continue;//sequence < currentStep did not conside
      }
      if(WorkflowStep.ACTION_TYPE_FORM_DRIVEN.equals(tempStep.getActionType())
          ||WorkflowStep.ACTION_TYPE_SYSTEM_AUTO.equals(tempStep.getActionType())){
        continue;//sys auto / form driven did not conside
      }
      
      int specialActionTakerCount = getSpecialActionTaker(actorDAO,tempStep.getID(),mtmWorkflowStepUserActors,permissions);
      Integer actionTakerCount=actorDAO.getListCountByWorkflowStepIDAndPermissions(tempStep.getID(),permissions);//all user count
      
      if(specialActionTakerCount>=actionTakerCount.intValue()&&actionTakerCount.intValue()>0){
        //when actionTaker count ==0,means it is assign at runtime,and all user is valid
        //the step's actionTaker all relate with some step's actionTaker
        param[0]=tempStep.getStepName();
        return false;
      }
    }
    return true;//pass the check
  }
  
  private int getSpecialActionTaker(MtmWorkflowStepUserActorDAObject actorDAO,Integer workflowStepID,MtmWorkflowStepUserActor[] mtmWorkflowStepUserActors,String[] permissions) throws ApplicationException{
    int count = 0;
    for(int i=0;i<mtmWorkflowStepUserActors.length;i++){
      count+=actorDAO.getListCountByWorkflowStepIDAndActorIDAndActorTypeAndPermissions(workflowStepID, mtmWorkflowStepUserActors[i].getActorID(), mtmWorkflowStepUserActors[i].getActorType(), permissions).intValue();
    }
    return count;
  }
  /**
   * check have currentUser's supervisor
   * @param stepUseractor
   * @param trackID
   * @return
   * @throws ApplicationException
   */
  private boolean hasSupervisor(MtmWorkflowStepUserActor stepUseractor,Integer trackID) throws ApplicationException{
    //for 'T' type only
    if(!MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO_OF_ACTION_TAKER.equals(stepUseractor.getActorType())){
      throw new ApplicationException("Method 'hasSupervisor(MtmWorkflowStepUserActor stepUseractor)' only for MtmWorkflowStepUserActor which actorType is 'T' ");
    }
    Integer stepID = stepUseractor.getActorID();
    WorkflowProgressDAObject progressDAO = new WorkflowProgressDAObject(this.sessionCon,this.dbConn);
    MtmWorkflowProgressUserRecordDAObject progressUserDAO = new MtmWorkflowProgressUserRecordDAObject(this.sessionCon,this.dbConn);
    
    List progressList = progressDAO.getCompleteListByStepIDAndTrackID(stepID, trackID);
    //get all of progress of this step
    for(Iterator it=progressList.iterator();it.hasNext();){
      WorkflowProgress progress = (WorkflowProgress)it.next();
      List progresssUserList = progressUserDAO.getCompletedUserProcessRecordByWorkflowProgressID(progress.getID());
      //check all of progressUser's supervisor is null
      for(Iterator it1 = progresssUserList.iterator();it1.hasNext();){
        MtmWorkflowProgressUserRecord tmpMtmWorkflowProgressUserRecord = (MtmWorkflowProgressUserRecord)it1.next();
        if(hasSupervisor(tmpMtmWorkflowProgressUserRecord.getUserRecordID())){
          return true;//have actionTaker which have supervisor
        }
      }
    }
    
    return false;
  }
  
  
  private boolean hasSupervisor(Integer userID) throws ApplicationException{
    UserRecordDAObject userDAO  = new UserRecordDAObject(this.sessionCon,this.dbConn);
    UserRecord record = (UserRecord)userDAO.getObjectByID(userID);
    return hasSupervisor(record);
  }
  
  private boolean hasSupervisor(UserRecord userRecord) throws ApplicationException{
    StaffRecordDAObject staffRecordDAO = new StaffRecordDAObject(sessionCon, dbConn);
    Integer linkID=userRecord.getUserLinkID();
    if(!Utility.isEmpty(linkID)){
      StaffRecord staffRecord=(StaffRecord)staffRecordDAO.getObjectByID(linkID);
      return !Utility.isEmpty(staffRecord.getReportToStaffRecordID());
    }
    return false;
  }
}
